package com.meida.common.utils;


import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.entity.EntityMap;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.*;


public class JsonUtils {

    private static ObjectMapper mapper;
    private static JsonGenerator jsonGenerator;

    private static final JsonFactory JSONFACTORY = new JsonFactory();
    private static SimpleFilterProvider filter;

    /**
     * 获取ObjectMapper实例
     */
    public static synchronized JsonGenerator getJsonGenerator() {
        try {
            jsonGenerator = getMapperInstance().getFactory().createGenerator(System.out, JsonEncoding.UTF8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonGenerator;
    }

    public static TypeReference<ResultBody<?>> getTypeReference(Class<?> cls) {
        return new TypeReference<ResultBody<?>>() {
            @Override
            public Type getType() {
                return cls;
            }
        };
    }

    @SuppressWarnings("deprecation")
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        ObjectMapper objectMapper = getMapperInstance();
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

    /**
     * 获取ObjectMapper实例
     */
    public static synchronized JsonGenerator getResponseJsonGenerator() {
        try {
            jsonGenerator = getMapperInstance().getFactory().createGenerator(System.out, JsonEncoding.UTF8);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonGenerator;
    }

    public static void setFilter(String filterName, String... property) {
        filter = new SimpleFilterProvider().setFailOnUnknownId(false);
        filter.addFilter(filterName, SimpleBeanPropertyFilter.serializeAllExcept(property));
    }

    /**
     * 获取ObjectMapper实例 Inclusion Inclusion.ALWAYS 全部列入 Inclusion
     * Inclusion.NON_DEFAULT 字段和对象默认值相同的时候不会列入 Inclusion Inclusion.NON_EMPTY
     * 字段为NULL或者""的时候不会列入 Inclusion Inclusion.NON_NULL 字段为NULL时候不会列入
     */
    public static synchronized ObjectMapper getMapperInstance() {
        if (mapper == null) {
            mapper = new ObjectMapper();
            mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
                @Override
                public void serialize(Object arg0, JsonGenerator arg1, SerializerProvider arg2) throws IOException, JsonProcessingException {
                    arg1.writeString("");
                }
            });
            mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 当找不到对应的序列化器时
            // 忽略此字段
            SimpleModule module = new SimpleModule();

            mapper.registerModule(module);
            //允许使用未带引号的字段名
            mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

            mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
            mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
            mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
            mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);// 允许空字符串转换为空数组
            mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);// 允许空字符串转换为空对象
            mapper.enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);// 允许空数组转换为空对象
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));// 所有日期格式都统一为以下样式
            mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);// 设置null值不参与序列化(字段不被显示)
            /*
             * mapper.setPropertyNamingStrategy(new PropertyNamingStrategy() {
             * private static final long serialVersionUID = 1L;
             *
             * // 反序列化时调用
             *
             * @Override public String nameForSetterMethod(MapperConfig<?>
             * config, AnnotatedMethod method, String defaultName) { return
             * method.getName().substring(3); } });
             */
        }
        return mapper;

    }

    /**
     * json 转lsit
     *
     * @param json
     * @param c
     * @return
     */
    public static <T> List<T> toList(String json, Class<T> c) {
        JSONArray jsonArray = JSONUtil.parseArray(json);
        return JSONUtil.toList(jsonArray, c);
    }

    /**
     * 将java对象转换成json字符串
     */
    public static String beanToJson(Object obj) {
        ObjectMapper objectMapper = getMapperInstance();
        String json = "";
        try {
            json = objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * json 转List
     *
     * @param json
     * @return
     */
    @SuppressWarnings("unchecked")
    public static List<?> jsonToList(String json) {
        ObjectMapper objectMapper = getMapperInstance();
        try {
            if (json != null && !"".equals(json.trim())) {
                JsonParser jsonParse = JSONFACTORY.createParser(new StringReader(json));
                ArrayList<Map<String, String>> arrayList = (ArrayList<Map<String, String>>) objectMapper.readValue(jsonParse, ArrayList.class);
                return arrayList;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json字符串转换成java对象
     */
    public static <T> T jsonToBean(String json, Class<T> cls) {
        ObjectMapper objectMapper = getMapperInstance();
        T object = null;
        try {
            object = objectMapper.readValue(json, cls);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }

    /**
     * 转换Json String 为 HashMap
     */
    public static EntityMap jsonToMap(String json, boolean collToString) {
        try {
            EntityMap map = getMapperInstance().readValue(json, EntityMap.class);
            if (collToString) {
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    if (entry.getValue() instanceof Collection || entry.getValue() instanceof Map) {
                        entry.setValue(beanToJson(entry.getValue()));
                    }
                }
            }
            return (EntityMap) map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 转换Json String 为 HashMap
     */
    public static Map<String, Object> jsonToMap2(String json, boolean collToString) {
        try {
            Map<String, Object> map = getMapperInstance().readValue(json, Map.class);
            if (collToString) {
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    if (entry.getValue() instanceof Collection || entry.getValue() instanceof Map) {
                        entry.setValue(beanToJson(entry.getValue()));
                    }
                }
            }
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把json解析成map，如果map内部的value存在jsonString，继续解析
     *
     * @param json
     * @param mapper
     * @return
     * @throws Exception
     */
    private static Map<String, Object> json2MapRecursion(String json, ObjectMapper mapper) throws Exception {
        if (json == null) {
            return null;
        }

        Map<String, Object> map = mapper.readValue(json, Map.class);

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            Object obj = entry.getValue();
            if (obj != null && obj instanceof String) {
                String str = ((String) obj);

                if (str.startsWith("[")) {
                    List<?> list = json2ListRecursion(str, mapper);
                    map.put(entry.getKey(), list);
                } else if (str.startsWith("{")) {
                    Map<String, Object> mapRecursion = json2MapRecursion(str, mapper);
                    map.put(entry.getKey(), mapRecursion);
                }
            }
        }

        return map;
    }

    /**
     * 深度转换json成map
     *
     * @param json
     * @return
     */
    public static Map<String, Object> json2mapDeeply(String json) throws Exception {
        return json2MapRecursion(json, getMapperInstance());
    }


    /**
     * 把json解析成list，如果list内部的元素存在jsonString，继续解析
     *
     * @param json
     * @param mapper 解析工具
     * @return
     * @throws Exception
     */
    private static List<Object> json2ListRecursion(String json, ObjectMapper mapper) throws Exception {
        if (json == null) {
            return null;
        }

        List<Object> list = mapper.readValue(json, List.class);

        for (Object obj : list) {
            if (obj != null && obj instanceof String) {
                String str = (String) obj;
                if (str.startsWith("[")) {
                    obj = json2ListRecursion(str, mapper);
                } else if (obj.toString().startsWith("{")) {
                    obj = json2MapRecursion(str, mapper);
                }
            }
        }

        return list;
    }

    /**
     * 将json字符串转换成java对象
     */
    public static <T> T jsonToBean(String json, TypeReference<?> typeReference) {
        ObjectMapper objectMapper = getMapperInstance();
        T object = null;
        try {
            object = objectMapper.readValue(json, typeReference);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return object;
    }

    /**
     * 转换Json String 为 HashMap
     */
    public static EntityMap jsonToEntityMap(String json) {
        EntityMap map = new EntityMap();
        try {
            map = getMapperInstance().readValue(json, EntityMap.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;

    }

    /**
     * 本方法封装了往前台设置的header,contentType等信息
     */
    public static void writeToWeb(String message, HttpServletResponse response) {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setContentType("text/html; charset=utf-8");
        try {
            response.getWriter().write(message);
            response.getWriter().close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 将json对象写入response
     */
    public static void writeToWeb(HttpServletResponse response, ResultBody j) {
        ObjectMapper objectMapper = getMapperInstance();
        try {
            if (filter != null) {
                objectMapper.writeValue(response.getWriter(), j);
            } else {
                objectMapper.writer(filter).writeValue(response.getWriter(), j);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * List 转换成json
     */
    public static String listToJson(HttpServletResponse response, Collection<?> list) {
        JsonGenerator jsonGenerator = null;
        StringWriter sw = new StringWriter();
        try {
            jsonGenerator = getJsonGenerator();
            if (filter != null) {
                getMapperInstance().writer(filter).writeValue(response.getWriter(), list);
                getMapperInstance().writer(filter).writeValue(sw, list);
            } else {
                getMapperInstance().writeValue(response.getWriter(), list);
                getMapperInstance().writeValue(sw, list);
            }
            jsonGenerator.flush();
            return sw.toString();
        } catch (Exception e) {
            return null;
        } finally {
            if (jsonGenerator != null) {
                try {
                    jsonGenerator.flush();
                    jsonGenerator.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 转换Java Bean 为 HashMap
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> beanToMap(Object o) {
        try {
            return getMapperInstance().readValue(beanToJson(o), HashMap.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 与javaBean json数组字符串转换为列表
     */
    public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) {
        JavaType javaType = getCollectionType(ArrayList.class, clazz);
        List<T> lst = null;
        try {
            lst = (List<T>) getMapperInstance().readValue(jsonArrayStr, javaType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return lst;
    }


}
